/*
 * @Author: WangShuai 1830773767@qq.com
 * @Date: 2025-05-07 21:09:45
 * @LastEditors: WangShuai 1830773767@qq.com
 * @LastEditTime: 2025-05-10 17:48:35
 * @FilePath: \Webgl-basic\src\6.绘制正三角形.js
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
 */
import {
    initShader,
    createBuffer,
    createCubeGem
} from '../lib/index'
import {
    mat4
} from 'gl-matrix';
import * as dat from 'dat.gui'
const canvas = document.querySelector('canvas')
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
//获取webgl上下文
const gl = canvas.getContext('webgl')
//定义点顶点着色器(字符串)
const vs_shader = /*glsl*/ `
  // 指定浮点数精度为中等精度  
  precision mediump float;
  attribute vec3 a_Position;
  attribute vec3 a_Color;
  varying vec3 v_Color;
  uniform mat4 u_ModelMatrix;  // 新增：模型变换矩阵
  uniform mat4 u_ViewMatrix;
  uniform mat4 u_ProjMatrix;
  void main(){
    // 应用模型-视图-投影变换
    gl_Position= u_ProjMatrix * u_ViewMatrix * u_ModelMatrix * vec4(a_Position,1.0);
    v_Color= a_Color;
  }`
//片元着色器
const fs_shader = /*glsl*/ `
precision mediump float;
varying vec3 v_Color;
void main(){
    gl_FragColor = vec4(v_Color,1.0);            
}`
//编译着色器,生成程序对象
const program = initShader(gl, vs_shader, fs_shader)
gl.program = program;

//视点位置
const viewObj = {
    eyeX: 3,
    eyeY: 3,
    eyeZ: 8,
    lookAtX: 0,
    lookAtY: 0,
    lookAtZ: 0,
    fov: 38,
    near: 0.2,
    far: 100,
    rotationSpeed: 0.5  // 新增：旋转速度控制
}

// 新增：旋转角度
let rotationX = 0;

// 存储着色器变量位置
const locations = {
    u_ModelMatrix: gl.getUniformLocation(program, 'u_ModelMatrix'),
    u_ViewMatrix: gl.getUniformLocation(program, 'u_ViewMatrix'),
    u_ProjMatrix: gl.getUniformLocation(program, 'u_ProjMatrix')
};

// 初始化模型矩阵
const modelMatrix = mat4.create();

// 渲染函数
const render = () => {
    // 更新旋转角度（仅绕X轴）
    rotationX += viewObj.rotationSpeed * 0.01;
    
    // 重置模型矩阵并应用旋转
    mat4.identity(modelMatrix);
    mat4.rotateX(modelMatrix, modelMatrix, rotationX);
    
    // 更新矩阵
    renderProMatrix();
    renderViewMatrix();
    
    // 设置模型矩阵
    gl.uniformMatrix4fv(locations.u_ModelMatrix, false, modelMatrix);
    
    // 绘制
    const n = createCube();
    gl.clearColor(0.0, 0.0, 0.0, 1.0);
    gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
    gl.drawElements(gl.TRIANGLES, n, gl.UNSIGNED_BYTE, 0);
    
    // 请求下一帧
    requestAnimationFrame(render);
}

const renderProMatrix = () => {
    let projMatrix = mat4.create();
    mat4.perspectiveNO(projMatrix, viewObj.fov * Math.PI / 180, window.innerWidth / window.innerHeight, viewObj.near, viewObj.far);
    gl.uniformMatrix4fv(locations.u_ProjMatrix, false, projMatrix);
}

const renderViewMatrix = () => {
    let viewMatrix = mat4.create();
    mat4.lookAt(viewMatrix, [viewObj.eyeX, viewObj.eyeY, viewObj.eyeZ], [viewObj.lookAtX, viewObj.lookAtY, viewObj.lookAtZ], [0, 1, 0]);
    gl.uniformMatrix4fv(locations.u_ViewMatrix, false, viewMatrix);
}

// 创建正方体函数
const createCube = () => {
    const {vertices, colors, indices} = getData();
    const config = new Map()
    config.set("a_Position", vertices);  
    config.set("a_Color", colors); 
    
    // 封装正方体的buffer
    const n = createCubeGem(gl, indices, config, {size: 3});
    
    // 启用深度测试
    gl.enable(gl.DEPTH_TEST);
    
    return n;
}

// 获取顶点数据
const getData = () => {
    // 顶点坐标
    var vertices = new Float32Array([
        // 前面
        1.0, 1.0, 1.0, -1.0, 1.0, 1.0, -1.0, -1.0, 1.0, 1.0, -1.0, 1.0,
        // 右面
        1.0, 1.0, 1.0, 1.0, -1.0, 1.0, 1.0, -1.0, -1.0, 1.0, 1.0, -1.0,
        // 上面
        1.0, 1.0, 1.0, 1.0, 1.0, -1.0, -1.0, 1.0, -1.0, -1.0, 1.0, 1.0,
        // 左面
        -1.0, 1.0, 1.0, -1.0, 1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, 1.0,
        // 下面
        -1.0, -1.0, -1.0, 1.0, -1.0, -1.0, 1.0, -1.0, 1.0, -1.0, -1.0, 1.0,
        // 后面
        1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, 1.0, -1.0, 1.0, 1.0, -1.0
    ]);
    
    // 颜色数据
    var colors = new Float32Array([
        0.4, 0.4, 1.0, 0.4, 0.4, 1.0, 0.4, 0.4, 1.0, 0.4, 0.4, 1.0,  // 前面(蓝色)
        0.4, 1.0, 0.4, 0.4, 1.0, 0.4, 0.4, 1.0, 0.4, 0.4, 1.0, 0.4,  // 右面(绿色)
        1.0, 0.4, 0.4, 1.0, 0.4, 0.4, 1.0, 0.4, 0.4, 1.0, 0.4, 0.4,  // 上面(红色)
        1.0, 1.0, 0.4, 1.0, 1.0, 0.4, 1.0, 1.0, 0.4, 1.0, 1.0, 0.4,  // 左面
        1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,  // 下面
        0.4, 1.0, 1.0, 0.4, 1.0, 1.0, 0.4, 1.0, 1.0, 0.4, 1.0, 1.0   // 后面
    ]);
    
    // 索引数据
    var indices = new Uint8Array([
        0, 1, 2, 0, 2, 3,    // 前面
        4, 5, 6, 4, 6, 7,    // 右面
        8, 9, 10, 8, 10, 11, // 上面
        12, 13, 14, 12, 14, 15, // 左面
        16, 17, 18, 16, 18, 19, // 下面
        20, 21, 22, 20, 22, 23  // 后面
    ]);

    return {
        vertices,
        colors,
        indices
    }
}

// 添加GUI控制
const gui = new dat.GUI();
const projFolder = gui.addFolder('Projection');
projFolder.add(viewObj, 'near', 0.1, 10, 0.01).onChange(renderProMatrix);
projFolder.add(viewObj, 'far', 1, 100, 0.1).onChange(renderProMatrix);
projFolder.add(viewObj, 'fov', 10, 90, 1).onChange(renderProMatrix);

const eyeFolder = gui.addFolder('Eye Position');
eyeFolder.add(viewObj, 'eyeX', -10, 10, 0.1).onChange(renderViewMatrix);
eyeFolder.add(viewObj, 'eyeY', -10, 10, 0.1).onChange(renderViewMatrix);
eyeFolder.add(viewObj, 'eyeZ', 1, 20, 0.1).onChange(renderViewMatrix);

const lookAtFolder = gui.addFolder('Look At');
lookAtFolder.add(viewObj, 'lookAtX', -5, 5, 0.1).onChange(renderViewMatrix);
lookAtFolder.add(viewObj, 'lookAtY', -5, 5, 0.1).onChange(renderViewMatrix);
lookAtFolder.add(viewObj, 'lookAtZ', -5, 5, 0.1).onChange(renderViewMatrix);

// 添加旋转控制
const rotationFolder = gui.addFolder('Rotation');
rotationFolder.add(viewObj, 'rotationSpeed', 0, 2, 0.01);

// 开始渲染循环
render();